﻿using Abp.AspNetCore.Mvc.Controllers;
using Abp.Dependency;
using Abp.Web.Models;
using Batman.Cms.Core.Models.Mvc;
using Batman.Cms.Core.Utils;
using Batman.Jianbei.Forum.Config;
using Batman.Jianbei.Forum.Core.Consts;
using Batman.Jianbei.Forum.Core.Domains;
using Batman.Jianbei.Forum.Core.Domains.Users;
using Batman.Jianbei.Forum.Core.Enums;
using Batman.Jianbei.Forum.Domains;
using Batman.Jianbei.Forum.Services.Users;
using Batman.Jianbei.Forum.Services.Weixins;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using Senparc.Weixin.MP.AdvancedAPIs;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;

namespace Batman.Jianbei.Forum.Controllers
{
    public class TokenController : AbpController
    {
        public UserRegister userRegister { get; set; }

        public UserManager<User> usermanager { get; set; }

        public SignInManager<User> _signInManager { get; set; }

        public WeixinUserManager WeixinUserManager { get; set; }

        public RoleCacheService RoleCacheService { get; set; }

        /// <summary>
        /// 角色上下文
        /// </summary>
        public Role role { get; set; }

        /// <summary>
        /// 获取Token
        /// </summary>
        /// <param name="code">微信授权，返回code</param>
        /// <returns></returns>
        public ActionResult Weixin(string code)
        {
            var appId = Config.WeixinSetting.weixin_app_id;
            var secret = Config.WeixinSetting.weixin_secret;

            var accessTokenResult = OAuthApi.GetAccessToken(appId, secret, code);
            var userInfo = OAuthApi.GetUserInfo(accessTokenResult.access_token, accessTokenResult.openid);

            Sex? sex = null;
            if (userInfo.sex == 1) sex = Sex.male;
            if (userInfo.sex == 2) sex = Sex.female;

            var weixinUser = new WeixinUser
            {
                AppId = WeixinSetting.weixin_app_id,
                Avatar = userInfo.headimgurl,
                City = userInfo.city,
                Country = userInfo.country,
                Nickname = userInfo.nickname,
                OpenId = accessTokenResult.openid,
                Province = userInfo.province,
                Sex = sex,
                UnionId = userInfo.unionid
            };


            weixinUser = WeixinUserManager.GetOrCreate(weixinUser);

            var isAdminOrSuperAdmin = false; // 默认不是管理员+

            if (!string.IsNullOrEmpty(weixinUser.UserId))
            {
                var adminOrSupperAdmins = RoleCacheService.GetAdminOrSupperAdminIds();
                isAdminOrSuperAdmin = adminOrSupperAdmins.Any(t => t == weixinUser.UserId);
            }

            var claims = new[] {
                new Claim(UserClaims.UserId, string.IsNullOrEmpty(weixinUser.UserId) ? string.Empty : weixinUser.UserId ),
                new Claim(UserClaims.WxUserId, weixinUser.Id),
                new Claim(UserClaims.OpenId, weixinUser.OpenId),
                new Claim(ClaimTypes.Name, weixinUser.Nickname),
                new Claim(UserClaims.IsAdminOrSuperAdmin, isAdminOrSuperAdmin.ToString()),
            };

            int expiresIn = 60 * 24; // 一天过期
            var token = JwtTokenUtil.GetToken(
                JwtBearerSetting.secret,
                JwtBearerSetting.valid_issuer,
                JwtBearerSetting.valid_audience,
                claims,
                expiresIn: expiresIn);

            return Json(new { token, expires = expiresIn, user = weixinUser, isAdminOrSuperAdmin });
        }


        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="username">用户名</param>
        /// <param name="password">密码</param>
        /// <returns></returns>
        public async Task<ActionResult> Login(string username, string password)
        {
            var user = usermanager.Users.FirstOrDefault(t => t.UserName == username);
            var result = new AjaxResponse();

            if (user == null)
            {
                result.Success = false;
                result.Error = new ErrorInfo($"用户不存在！");
            }
            else
            {
                var signInResult = await _signInManager.PasswordSignInAsync(user, password, true, false);

                if (!signInResult.Succeeded)
                {
                    result.Success = false;
                    var msg = "密码错误！";
                    if (signInResult.IsLockedOut) msg = "账号已锁定，请联系管理员";
                    result.Error = new ErrorInfo(msg);
                }
                else
                {
                    var claims = new[] {
                        new Claim(UserClaims.UserId, user.Id),
                        new Claim(ClaimTypes.Name, user.Id),
                        new Claim(ClaimTypes.NameIdentifier, user.Id),
                    };
                    // TODO:除了Name，其他的在User对象中都无法获取，需要检查

                    // 走到这里，就是登录成功
                    int expiresIn = 30;
                    var token = JwtTokenUtil.GetToken(
                        JwtBearerSetting.secret,
                        JwtBearerSetting.valid_issuer,
                        JwtBearerSetting.valid_audience,
                        claims,
                        expiresIn: expiresIn);

                    return Json(new
                    {
                        token,
                        expires = expiresIn,
                        name = user.UserName
                    });
                }
            }

            return Json(result);
        }

        [HttpGet]
        public IActionResult Test()
        {
            var claims = new Claim[]
            {
                        new Claim(ClaimTypes.Name,"wolf"),
                        new Claim(ClaimTypes.Role,"admin"),
            };
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JwtBearerSetting.secret));
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            var token = new JwtSecurityToken(JwtBearerSetting.valid_issuer,
                JwtBearerSetting.valid_audience, claims, DateTime.Now,
                DateTime.Now.AddHours(30), creds);
            return Json(new { token = new JwtSecurityTokenHandler().WriteToken(token) });
        }

#if DEBUG
        /// <summary>
        /// 单元测试用登录
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public IActionResult LoginByWxUserId(string userId)
        {
            var repo = IocManager.Instance.Resolve<Abp.Domain.Repositories.IRepository<WeixinUser, string>>();

            var user = repo.GetAll().Where(t => t.UserId == userId).FirstOrDefault();

            if (user == null) return Json(new ResponseBase(false, "User Not Found"));

            var claims = new[] {
                new Claim(UserClaims.WxUserId, user.Id),
                new Claim(UserClaims.OpenId, user.OpenId),
                new Claim(ClaimTypes.Name, user.Nickname),
            };

            int expiresIn = 30;
            var token = JwtTokenUtil.GetToken(
                JwtBearerSetting.secret,
                JwtBearerSetting.valid_issuer,
                JwtBearerSetting.valid_audience,
                claims,
                expiresIn: expiresIn);

            return Json(new { token, expires = expiresIn, user = user });

        }
#endif
    }
}
